﻿using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;

namespace UnityView
{
    public enum AnimationEase
    {
        Linear,
        EaseIn,
        EaseOut,
        EaseInEaseOut,
        Spring,
        SpringShake
    }

    public delegate void AnimationDelegate();

    public delegate void AnimationCompletion();

    public class UIAnimation
    {
        private UIAnimation() { }

        // 动画管理
        protected static List<AnimationGroup> AliveAnimation = new List<AnimationGroup>();
        protected static List<AnimationGroup> ObsoleteAnimation = new List<AnimationGroup>();

        public const float DefaultDuration = 0.25f;

        public static bool Animating = false;
        public static bool EnableAnimation = true;

        public static bool OnAnimate()
        {
            return Animating;
        }

        public static AnimationFunctionLinear Linear = new AnimationFunctionLinear();
        public static AnimationFunctionEaseIn EaseIn = new AnimationFunctionEaseIn();
        public static AnimationFunctionEaseOut EaseOut = new AnimationFunctionEaseOut();
        public static AnimationFunctionEaseInOut EaseInOut = new AnimationFunctionEaseInOut();
        public static AnimationFunctionSpring Spring = new AnimationFunctionSpring();
        public static AnimationFunctionSpringShake SpringShake = new AnimationFunctionSpringShake();

        public static AnimationGroup CurrentGroup;
        public static AnimationGroup Animate(AnimationDelegate animation)
        {
            return Animate(animation, DefaultDuration, 0, Linear, null);
        }
        public static AnimationGroup Animate(AnimationDelegate animation, AnimationCompletion completion)
        {
            return Animate(animation, DefaultDuration, 0, Linear, completion);
        }

        public static AnimationGroup Animate(AnimationDelegate animation, float duration, float delay = 0)
        {
            return Animate(animation, duration, delay, Linear, null);
        }

        public static AnimationGroup Animate(AnimationDelegate animation, float duration, AnimationEase ease)
        {
            return Animate(animation, duration, 0, ease, null);
        }

        public static AnimationGroup Animate(AnimationDelegate animation, float duration, AnimationFunction function)
        {
            return Animate(animation, duration, 0, function, null);
        }

        public static AnimationGroup Animate(AnimationDelegate animation, float duration, float delay, AnimationEase ease, AnimationCompletion completion)
        {
            AnimationFunction function = null;
            switch (ease)
            {
                case AnimationEase.Linear:
                    function = Linear;
                    break;
                case AnimationEase.EaseIn:
                    function = EaseIn;
                    break;
                case AnimationEase.EaseOut:
                    function = EaseInOut;
                    break;
                case AnimationEase.EaseInEaseOut:
                    function = EaseInOut;
                    break;
                case AnimationEase.Spring:
                    function = Spring;
                    break;
            }
            return Animate(animation, duration, delay, function, completion);
        }

        public static AnimationGroup Animate(AnimationDelegate animation, float duration, float delay, AnimationFunction function, AnimationCompletion completion)
        {
            CurrentGroup = new AnimationGroup(duration, delay, function, completion);
            BeginAnimate();
            animation();
            EndAnimate();
            return CurrentGroup;
        }

        public static void BeginAnimate()
        {
            Animating = EnableAnimation;
        }

        public static void EndAnimate()
        {
            Animating = false;
            AliveAnimation.Add(CurrentGroup);
        }

        public static void PauseAnimation(AnimationGroup group)
        {
            PauseAnimation(group.GroupID);
        }

        public static void PauseAnimation(int id)
        {
            AliveAnimation.RemoveAll(g => g.GroupID == id);
        }

        public static void RestoreAnimation(AnimationGroup group)
        {
            if (AliveAnimation.All(g => g.GroupID != group.GroupID)) AliveAnimation.Add(group);
        }
        
        public static void FinishAnimation(AnimationGroup group)
        {
            PauseAnimation(group.GroupID);
            group.Finish();
        }

        public static void Append(AbsAnimationAction action)
        {
            CurrentGroup.Actions.Add(action);
        }

        public static void Update()
        {
            foreach (var group in AliveAnimation)
            {
                group.Update();
                if (group.IsFinish()) ObsoleteAnimation.Add(group);
            }
            if (ObsoleteAnimation.Count > 0)
            {
                foreach (var group in ObsoleteAnimation)
                {
                    AliveAnimation.Remove(group);
                    group.Finish();
                }
                ObsoleteAnimation.Clear();
            }
        }
    }

    public class UIAnimationManager : MonoBehaviour
    {

    }

    public class AnimatableAttribute : Attribute
    {
    }
}
